package com.mgy.example.dao.config.db;

import com.mgy.example.domain.TableRouter;
import com.mgy.example.utils.DbUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.*;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.*;

/**
 * 自定义拦截器，在sql执行前拦截
 *
 * @author mgy
 */
@Intercepts(@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}))
public class MybatisInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        if (invocation.getTarget() instanceof RoutingStatementHandler) {
            RoutingStatementHandler statementHandler = (RoutingStatementHandler) invocation.getTarget();
            BoundSql boundSql = statementHandler.getBoundSql();
            String sql = boundSql.getSql();
            Integer dbNo = null;
            List<TableRouter> tableRouters = getTableRouter(boundSql);
            for (TableRouter tableRouter : tableRouters) {
                if (tableRouter.getDbNo() != null) {
                    dbNo = tableRouter.getDbNo();
                }
                if (tableRouter.getTableNo() != null && StringUtils.isNotBlank(tableRouter.getLogicTable())) {
                    sql = sql.replaceAll(" " + tableRouter.getLogicTable() + " ", " " + tableRouter.getLogicTable() + "_" + tableRouter.getTableNo() + " ");
                }
            }
            DataSourceRouterHolder.setDbNo(dbNo);
            //修改sql
            Field field = boundSql.getClass().getDeclaredField("sql");
            field.setAccessible(true);
            field.set(boundSql, sql);


        }
        Object obj = invocation.proceed();
        DataSourceRouterHolder.removeDbNo();
        return obj;
    }

    @Override
    public Object plugin(Object o) {
        return Plugin.wrap(o, this);
    }

    @Override
    public void setProperties(Properties properties) {
        //此处可以接收到配置文件的property参数
        System.out.println(properties.getProperty("name"));
    }

    private List<TableRouter> getTableRouter(BoundSql boundSql) {
        Object parameters = boundSql.getParameterObject();
        System.out.println(parameters.getClass().toString());
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();

        List<String> parameterNameArr = new ArrayList<>();
        List<Class> parameterTypeArr = new ArrayList<>();
        List<Object> parameterValueArr = new ArrayList<>();

        if (parameters instanceof Map) {
            Map<String, Object> map = (Map<String, Object>) parameters;
            Set<Map.Entry<String, Object>> entrys = map.entrySet();

            for (Map.Entry<String, Object> entry : entrys) {
                if (StringUtils.equals(entry.getKey(), "param1")) {
                    break;
                }
                parameterNameArr.add(entry.getKey());
                parameterTypeArr.add(entry.getValue().getClass());
                parameterValueArr.add(entry.getValue());
            }

        } else {
            parameterNameArr.add(parameterMappings.get(0).getProperty());
            parameterTypeArr.add(parameterMappings.get(0).getJavaType());
            parameterValueArr.add(parameters);
        }
        return DbUtil.getTableRouter(parameterNameArr.toArray(new String[0]), parameterTypeArr.toArray(new Class[0]), parameterValueArr.toArray());
    }


}
